package com.company.eos.service.impl;

import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.company.eos.common.BusinessException;
import com.company.eos.common.ErrorEnum;
import com.company.eos.common.GlobalConstant;
import com.company.eos.common.GlobalException;
import com.company.eos.common.util.*;
import com.company.eos.controller.form.user.ResetPasswordDTO;
import com.company.eos.controller.form.user.UpdatePasswordDTO;
import com.company.eos.mapper.UserMapper;
import com.company.eos.domain.LoginAuthor;
import com.company.eos.domain.User;
import com.company.eos.service.LoginAuthorService;
import com.company.eos.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;

/**
 * @author: Song, Wei
 * @date: 2022-01-13
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
        implements UserService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private MailClient mailClient;
    @Autowired
    private TemplateEngine templateEngine;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private LoginAuthorService loginAuthorService;

    @Value("${wx.app-id}")
    private String appId;

    @Value("${wx.app-secret}")
    private String appSecret;

    /**
     * 根据userId查询用户的权限
     *
     * @param userId 用户ID
     * @return 权限列表
     */
    @Override
    public Set<String> searchUserPermissions(int userId) {
        Set<String> permissions = userMapper.searchUserPermissions(userId);
        return permissions;
    }

    @Override
    public User selectUserByEmail(String email) {
        return userMapper.selectOne(Wrappers.lambdaQuery(User.class).eq(User::getEmail, email));
    }

    /**
     * 查询用户角色
     *
     * @param userId 用户ID
     * @return 用户ID角色列表
     */
    @Override
    public ArrayList<String> searchUserRoles(int userId) {
        return userMapper.searchUserRoles(userId);
    }

    /**
     * 根据ID查询用户信息
     *
     * @param userId 用户ID
     * @return 用户信息
     */
    @Override
    public HashMap searchById(int userId) {
        HashMap map = userMapper.searchById(userId);
        return map;
    }

    @Override
    public User selectById(int userId) {
        User user = userMapper.selectById(userId);
        return user;
    }

    @Override
    public HashMap searchUserSummary(int userId) {
        HashMap map = userMapper.searchUserSummary(userId);
        return map;
    }

    /**
     * 查询全部用户名称
     *
     * @return 用户名称
     */
    @Override
    public ArrayList<HashMap> searchAllUser() {
        return userMapper.searchAllUser();
    }

    /**
     * 查询用户分页记录
     *
     * @param param param
     * @return 用户分页记录
     */
    @Override
    public PageUtils searchUserByPage(HashMap param) {
        ArrayList<HashMap> list = userMapper.searchUserByPage(param);
        //  修复分页查询用户数量错误
        //  long count = userMapper.searchUserCount(param);
        Long count = userMapper.selectCount(null);
        int start = (Integer) param.get("start");
        int length = (Integer) param.get("length");
        return new PageUtils(list, count, start, length);
    }

    /**
     * 添加用户
     *
     * @param user 用户实体
     * @return 影响行数
     */
    @Override
    public int insert(User user) {
        return userMapper.insert(user);
    }

    /**
     * 修改用户
     *
     * @param param 修改参数
     * @return 修改的数量
     */
    @Override
    public int update(HashMap param) {
        return userMapper.updateUser(param);
    }

    /**
     * 删除用户
     *
     * @param ids 用户id
     * @return 删除数量
     */
    @Override
    public int deleteUserByIds(Integer[] ids) {
        return userMapper.deleteUserByIds(ids);
    }

    /**
     * 员工离职
     *
     * @param ids 用户ID
     * @return 离职数量
     */
    @Override
    public int dismissUserByIds(Integer[] ids) {
        return userMapper.dismissUserByIds(ids);
    }

    /**
     * 查询用户名称和部门
     *
     * @param userId 用户ID
     * @return 名称和部门信息
     */
    @Override
    public HashMap searchNameAndDept(int userId) {
        return userMapper.searchNameAndDept(userId);
    }

    /**
     * 发送找回密码的验证码邮箱
     *
     * @param email 目标邮箱
     * @return 发送成功返回1
     */
    @Override
    public Integer sendVerify(String email) {
        JSONObject jsonObject = JSONUtil.parseObj(email);
        email = jsonObject.getStr("email");
        log.info("发送验证码，参数：{}", email);
        // 发送验证码邮件
        Context context = new Context();
        context.setVariable("email", email);
        String code = RandomUtil.randomNumber(4);
        context.setVariable("verify", code);
        // 模板引擎调用网页，将其中的数据填充之后，生成一个 HTML 网页字符串对象，格式化网页
        String process = templateEngine.process("/mail/forget", context);
        mailClient.sendMail(email, "企业账户-忘记密码", process);
        // 将验证码保存在 redis 中
        redisUtil.setCacheObject(RedisKeyUtil.getVerifyKey(email), code, GlobalConstant.VERIFY_AVAILABLE_TIME, TimeUnit.SECONDS);
        return 1;
    }

    /**
     * 重置用户密码
     *
     * @param dto dto对象，包含邮箱、两次新密码、验证码
     * @return 重置数量
     */
    @Override
    public Integer resetPassword(ResetPasswordDTO dto) {
        if (dto.getPassword() == null || dto.getConfirmPassword() == null ||
                dto.getAccount() == null || dto.getVerify() == null) {
            throw new BusinessException(ErrorEnum.INPUT_NULL_ERROR);
        }
        String pattern = "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$";
        boolean matches = Pattern.matches(pattern, dto.getAccount());
        if (!matches) {
            throw new BusinessException(ErrorEnum.ACCOUNT_SHOULD_BE_EMAIL);
        }
        Object verifyObj = redisUtil.getCacheObject(RedisKeyUtil.getVerifyKey(dto.getAccount()));
        Optional.ofNullable(verifyObj).orElseThrow(() -> new GlobalException(ErrorEnum.VERIFY_NOT_EXIST));
        String verify = verifyObj.toString();
        if (!dto.getPassword().equals(dto.getConfirmPassword())) {
            throw new BusinessException(ErrorEnum.PASSWORD_NOT_CONSISTENT);
        }
        if (!dto.getVerify().equals(verify)) {
            throw new BusinessException(ErrorEnum.VERIFY_INCORRECT);
        }
        LoginAuthor loginAuthor = loginAuthorService.getByAccount(dto.getAccount());
        Optional.ofNullable(loginAuthor).orElseThrow(() -> new BusinessException(ErrorEnum.EMAIL_NOT_EXIST));
        UpdatePasswordDTO updatePasswordDTO = new UpdatePasswordDTO(loginAuthor.getUserId(),
                dto.getPassword());
        return loginAuthorService.updatePassword(updatePasswordDTO);
    }

    /**
     * 获取用户对应的管理员
     *
     * @param user 用户
     * @return 管理员用户
     */
    @Override
    public User getDepManager(User user) {
        Integer deptId = user.getDeptId();
        // 获取同部门员工
        List<User> users = userMapper.selectList(Wrappers.lambdaQuery(User.class)
                .eq(User::getDeptId, deptId));
        // 获取自己的部门经理
        if (users != null) {
            for (User user1 : users) {
                ArrayList<String> strings = this.searchUserRoles(user1.getId());
                if (strings.contains("2")) {
                    return user1;
                }
            }
        }
        // 没有部门经理，获取总经理
        List<User> users1 = userMapper.selectList(null);
        for (User user1 : users1) {
            ArrayList<String> strings = this.searchUserRoles(user1.getId());
            if (strings.contains("1")) {
                return user1;
            }
        }
        // 获取管理员
        return userMapper.selectById(1);
    }
}
